package sketch.ast;

import java.util.List;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.Statement;
import org.eclipse.jdt.core.dom.TypeDeclaration;

import sketch.util.Checker;
import sketch.util.SketchUtil;

public class ASTUtilTest extends TestCase {
	
	public static Test suite() {
        return new TestSuite(ASTUtilTest.class);
    }
	
	public void testExtractHoles() {
		String filePath = "./testfiles/sketch/ast/TreeMapSketchExecutionForTest.java";
		CompilationUnit unit = ASTUtils.astRoot(filePath);
		List<AbstractTypeDeclaration> types = ASTUtils.typeDeclarations(unit);
		TypeDeclaration typeDeclaration = ASTUtils.getTypeDeclaration(types, "GenTest");
		MethodDeclaration methodDeclaration = ASTUtils.getMethodByName(typeDeclaration, "scratchTest");
		//check that scratchTest must exist
		Checker.checkNull(methodDeclaration, "There is no method called scratchTest");
		
		HoleExtractionVisitor visitor = new HoleExtractionVisitor(methodDeclaration);
		visitor.visit(methodDeclaration);
		
		MethodDeclarationWithHoles methodHoles = visitor.getTransformedMethod();
		methodHoles.removeAnnotation();
		methodHoles.rename("testGen1");
		SketchUtil.stdln(methodHoles);
	}
	
	public void testParseStatements() {
		String singleStatement =  "List<String> list=new LinkedList<String>();";
		Block block = ASTUtils.parseStatements(singleStatement);
		SketchUtil.stdln(block);
		assertTrue(block.statements().get(0).toString().trim().equals(singleStatement));
	}
	
	public void testParseMultipleStatements() {
		String singleStatement1 =  "List<String> list1=new LinkedList<String>();";
		String singleStatement2 =  "List<String> list2=new LinkedList<String>();";
		Block block = ASTUtils.parseStatements(singleStatement1 + singleStatement2);
		SketchUtil.stdln(block);
		assertTrue(block.statements().get(0).toString().trim().equals(singleStatement1));
		assertTrue(block.statements().get(1).toString().trim().equals(singleStatement2));
	}
	
	public void testParseBlock() {
		String blockStr =  "{List<String> list1=new LinkedList<String>();}";
		Block block = ASTUtils.parseStatements(blockStr);
		SketchUtil.stdln(block);
	}
	
	public void testParseBlockWithSameResult() {
		String blockStr =  "List<String> list1=new LinkedList<String>();";
		Block block = ASTUtils.parseStatements(blockStr);
		String blockAfterParsing = block.toString();
		
		StringBuilder sb = new StringBuilder();
		List<Statement> statements = block.statements();
		for(Statement s : statements) {
			sb.append(s.toString());
		}
		Block recover = ASTUtils.parseStatements(sb.toString());
		SketchUtil.stdln(recover);
		assertTrue(block.toString().equals(recover.toString()));
	}
	
	public void testMethodWithAnnotation() {
		String filePath = "./testfiles/sketch/specs/SampleCode.java";
		CompilationUnit unit = ASTUtils.astRoot(filePath);
		List<MethodDeclaration> methods = ASTUtils.getMethodsWithAnnotation(unit, "TestSketch");
		assertEquals(7, methods.size());
	}
	
	public void testDeepCopySame() {
		String blockStr =  "{List<String> list1=new LinkedList<String>();}";
		Block block = ASTUtils.parseStatements(blockStr);
		Block block1 = ASTUtils.deepClone(block);
		assertFalse(block.equals(block1));
	}
}